package com.sscw.tcp.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.guaike.core.redis.annotation.TryLock;
import com.guaike.core.redis.enums.LockModel;
import com.sscw.tcp.dao.*;
import com.sscw.tcp.constant.TcpCommandCodeConstant;
import com.sscw.tcp.entity.*;
import com.sscw.tcp.enums.DailyTaskActionEnum;
import com.sscw.tcp.enums.PeriodEnum;
import com.sscw.tcp.enums.TaskStatusEnum;
import com.sscw.tcp.utils.TcpUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.Socket;
import java.time.LocalDate;
import java.util.*;

@Slf4j
@Service
@AllArgsConstructor
public class BaseUtilService {

    private final MRecordTaskDailyDAO mRecordTaskDailyDAO;
    private final MConfTaskDailyDAO mConfTaskDailyDAO;
    private final MConfTaskDAO mConfTaskDAO;
    private final MRecordTaskDAO mRecordTaskDAO;
    private final GConfDeviceDAO gConfDeviceDAO;

    /**
     * 初始化每日任务
     *
     * @param key
     * @param userId
     * @param today
     * @return
     */
    @TryLock(lockKey = "#key", lockModel = LockModel.REENTRANT)
    public Boolean setDailyTask(String key, Long userId, LocalDate today) {
        List<MRecordTaskDailyPO> pos = mRecordTaskDailyDAO.findUserTodayList(userId, today);
        if (CollectionUtils.isNotEmpty(pos)) {
            return Boolean.TRUE;
        }
        int day = today.getDayOfMonth();
        List<MConfTaskDailyPO> dailyPOS = mConfTaskDailyDAO.findAll(MConfTaskDailyPO::getSortIndex, Boolean.TRUE);
        pos = new ArrayList<>();
        List<MRecordTaskDailyPO> finalPos = pos;
        dailyPOS.forEach(po -> {
            if (po.getAction().equals(DailyTaskActionEnum.receive.getCode())
                    && po.getPeriod().equals(PeriodEnum.monthly.getCode())) {
                String[] split = po.getPeriodPoint().split(",");
                List<String> list = Arrays.asList(split);
                if (!list.contains(String.valueOf(day))) {
                    return;
                }
            }
            MRecordTaskDailyPO dailyPO = new MRecordTaskDailyPO();
            dailyPO.setUserId(userId);
            dailyPO.setTaskId(po.getId());
            dailyPO.setTaskName(po.getTaskName());
            dailyPO.setAction(po.getAction());
            dailyPO.setIcon(po.getImage());
            dailyPO.setPrize(po.getPinecone());
            dailyPO.setThreshold(po.getThreshold());
            dailyPO.setRecordDate(today);
            if (po.getAction().equals(DailyTaskActionEnum.receive.getCode())) {
                dailyPO.setStatus(TaskStatusEnum.unclaimed.getCode());
            } else {
                dailyPO.setStatus(TaskStatusEnum.go_complete.getCode());
            }
            finalPos.add(dailyPO);
        });
        mRecordTaskDailyDAO.saveBatch(finalPos);
        return Boolean.TRUE;
    }

    @Transactional
    public void dealDailyTaskAllComplete(Long userId, LocalDate today) {
        LambdaQueryWrapper<MRecordTaskDailyPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MRecordTaskDailyPO::getUserId, userId);
        queryWrapper.eq(MRecordTaskDailyPO::getRecordDate, today);
        queryWrapper.ne(MRecordTaskDailyPO::getAction, DailyTaskActionEnum.all_complete.getCode());
        long allTaskCount = mRecordTaskDailyDAO.count(queryWrapper);
        queryWrapper.ne(MRecordTaskDailyPO::getStatus, TaskStatusEnum.go_complete.getCode());
        long allCompleteTaskCount = mRecordTaskDailyDAO.count(queryWrapper);
        if (allTaskCount == allCompleteTaskCount) {
            LambdaQueryWrapper<MRecordTaskDailyPO> query = new LambdaQueryWrapper<>();
            query.eq(MRecordTaskDailyPO::getUserId, userId);
            query.eq(MRecordTaskDailyPO::getRecordDate, today);
            query.eq(MRecordTaskDailyPO::getAction, DailyTaskActionEnum.all_complete.getCode());
            query.eq(MRecordTaskDailyPO::getStatus, TaskStatusEnum.go_complete.getCode());
            long count = mRecordTaskDailyDAO.count(query);
            if (count > 0) {
                mRecordTaskDailyDAO.updateCompleteTask(userId, today);
            }
        }
    }

    /**
     * 初始化长期任务
     *
     * @param key
     * @param userId
     * @return
     */
    @TryLock(lockKey = "#key", lockModel = LockModel.REENTRANT)
    public Boolean setTask(String key, Long userId) {
        List<MConfTaskPO> taskPOS = mConfTaskDAO.findAll(MConfTaskPO::getSortIndex, Boolean.TRUE);
        List<MRecordTaskPO> list = new ArrayList<>();
        taskPOS.forEach(po -> {
            MRecordTaskPO recordTaskPO = mRecordTaskDAO.findUserOne(userId, po.getId());
            if (Objects.isNull(recordTaskPO)) {
                recordTaskPO = new MRecordTaskPO();
                recordTaskPO.setUserId(userId);
                recordTaskPO.setTaskId(po.getId());
                recordTaskPO.setTaskName(po.getTaskName());
                recordTaskPO.setAction(po.getAction());
                recordTaskPO.setIcon(po.getImage());
                recordTaskPO.setPrize(po.getPinecone());
                recordTaskPO.setThreshold(po.getThreshold());
                recordTaskPO.setVipLevel(po.getVipLevel());
                recordTaskPO.setStatus(TaskStatusEnum.go_complete.getCode());
                list.add(recordTaskPO);
            }
        });
        mRecordTaskDAO.saveBatch(list);
        return Boolean.TRUE;
    }


    /**
     * 发送结算街机娱乐
     *
     * @param deviceId
     */
    public void settleMachine(Long deviceId) throws IOException {
        GConfDevicePO devicePO = gConfDeviceDAO.findById(deviceId);
        Socket socket = TcpUtils.findSocket(devicePO.getSerialNumber());
        if (Objects.nonNull(socket)) {
            TcpUtils.sendMessage(socket, TcpCommandCodeConstant.STOP);
            TcpUtils.sendMessage(socket, TcpCommandCodeConstant.SETTLE_APPLY);
        }
    }
}
